#include <cstring>
#include <iostream>

class String {

public:
  String(const char *s = nullptr) {
    std::cout << "String(const char*)" << std::endl;
    if (s) {
      _data = new char[strlen(s) + 1];
      strcpy_s(_data, strlen(s) + 1, s);
    } else {
      _data = new char[1];
      _data[0] = '\0';
    }
  }

  ~String() {
    delete[] _data;
    _data = nullptr;
  }

  String(const String &other) {
    std::cout << "String(const String&)" << std::endl;
    _data = new char[strlen(other._data) + 1];
    strcpy_s(_data, strlen(other._data) + 1, other._data);
  }

  String &operator=(const String &other) {
    std::cout << "operator=(const String&)" << std::endl;
    if (this == &other)
      return *this;
    delete[] _data;
    _data = new char[strlen(other._data) + 1];
    strcpy_s(_data, strlen(other._data) + 1, other._data);
    return *this;
  }

  String(String &&other) {
    std::cout << "String(String &&)" << std::endl;
    _data = other._data;
    other._data = nullptr;
  }

  String &operator=(String &&other) {
    std::cout << "operator=(String &&)" << std::endl;
    if (this == &other)
      return *this;
    delete[] _data;
    _data = other._data;
    other._data = nullptr;
    return *this;
  }

  size_t length() const { return strlen(_data); }

  const char *c_str() const { return _data; }

private:
  char *_data;
};

std::ostream &operator<<(std::ostream &os, const String &str) {
  os << str.c_str();
  return os;
}

int main() {
  String s1;          // 默认构造，使用默认参数nullptr
  String s2{"hello"}; // 默认构造
  String s3{s2};      // 拷贝构造
  String s4{String{"this is a tmp String"}}; // 默认构造临时对象
  s1 = s2;                                   // 拷贝赋值
  s1 = String{"rvalue String"};              // 移动赋值
  std::cout << s1 << std::endl;
  std::cout << s1.length() << std::endl;

  String ss{"self move assignment"};
  ss = std::move(ss);
  std::cout << ss;
}